//-----------------------------------------------------------------------
// <copyright file="SpecifiedSubscriptionSelectorPolicy.cs" company="iron9light">
//      Copyright (c) iron9light. All rights reserved.
// </copyright>
// <author>iron9light</author>
//-----------------------------------------------------------------------

namespace EventBrokerExtension
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;

    using Microsoft.Practices.ObjectBuilder2;
    using Microsoft.Practices.Unity.Utility;

    /// <summary>
    /// An implemnetation of <see cref="ISubscriptionSelectorPolicy"/> which returns
    /// the set of specific subscription that the selector was configured with.
    /// </summary>
    public class SpecifiedSubscriptionSelectorPolicy : ISubscriptionSelectorPolicy
    {
        private readonly List<SubscriptionInfo> subscriptionInfos = new List<SubscriptionInfo>();

        public void Add(MethodInfo method, string eventTopic)
        {
            this.subscriptionInfos.Add(new SubscriptionInfo(eventTopic, method));
        }

        public IEnumerable<SubscriptionInfo> GetSubscriptionInfos(IBuilderContext context)
        {
            Type typeToBuild = BuildKey.GetType(context.BuildKey);

            foreach (SubscriptionInfo info in this.subscriptionInfos)
            {
                SubscriptionInfo subscriptionInfo;

                ReflectionHelper typeReflector = new ReflectionHelper(info.Method.DeclaringType);
                MethodReflectionHelper methodReflector = new MethodReflectionHelper(info.Method);

                if (!methodReflector.MethodHasOpenGenericParameters && !typeReflector.IsOpenGeneric)
                {
                    subscriptionInfo = info;
                }
                else
                {
                    Type[] closedMethodParameterTypes =
                            methodReflector.GetClosedParameterTypes(typeToBuild.GetGenericArguments());
                    MethodInfo method = typeToBuild.GetMethod(info.Method.Name, closedMethodParameterTypes);
                    subscriptionInfo = new SubscriptionInfo(info.EventTopic, method);
                }

                yield return subscriptionInfo;
            }
        }
    }
}